/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.workflowDesign.service.impl;

import com.koron.workflow.api.service.ActivitiService;
import com.koron.workflow.common.bean.PageBean;
import com.koron.workflow.common.bean.StaffBean;
import com.koron.workflow.common.util.BusinessCode;
import com.koron.workflow.common.util.DisposeBeanUtil;
import com.koron.workflow.common.util.WorkflowUtil;
import com.koron.workflow.workflowDesign.bean.*;
import com.koron.workflow.workflowDesign.mapper.ProcessMapper;
import com.koron.workflow.workflowDesign.mapper.ProcessSetMapper;
import com.koron.workflow.workflowDesign.service.ProcessService;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.swan.bean.MessageBean;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 模版管理
 */
@Service
public class ProcessServiceImpl implements ProcessService {
    private static final Logger logger = LoggerFactory.getLogger(ProcessServiceImpl.class);

    @Autowired
    private ActivitiService activitiService;

    @TaskAnnotation("queryForList")
    @Override
    public PageBean<ProcessQueryBean> queryForList(SessionFactory factory, StaffBean user, String appId, String setId,
                                                   String code, String name, Integer status,
                                                   Integer page, Integer pageSize) {
        ProcessSetMapper processSetMapper = factory.getMapper(ProcessSetMapper.class);
        // 根据用户帐号 查询系统管理员ID
        String administratorId = processSetMapper.queryAdminIdByUsercode(user.getAccount());
        ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
        List<ProcessQueryBean> list = mapper.queryForList(administratorId, appId, setId, code, name, status, page, pageSize);
        Integer total = null;
        if (page != null || pageSize != null) {
            total = mapper.countQueryForList(administratorId, appId, setId, code, name, status);
        }
        return new PageBean<>(list, total);
    }

    @TaskAnnotation("queryForObject")
    @Override
    public ProcessQueryBean queryForObject(SessionFactory factory, String id) {
        return factory.getMapper(ProcessMapper.class).queryForObject(id);
    }

    @TaskAnnotation("save")
    @Override
    public MessageBean save(SessionFactory factory, StaffBean user, ProcessUpdateBean bean) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            if (StringUtils.isEmpty(bean.getAppId()) || StringUtils.isEmpty(bean.getSetId()) ||
                    StringUtils.isEmpty(bean.getCode()) || StringUtils.isEmpty(bean.getName())) {
                msg.setCode(BusinessCode.EMPTY_PARAM.getCode());
                msg.setDescription(BusinessCode.EMPTY_PARAM.getDescription());
                return msg;
            }
            DisposeBeanUtil.disposeInsert(user, bean);
            ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
            // 验证 code 是否已经存在
            if (mapper.verifyCode(bean.getCode(), bean.getSetId(), null) > 0) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("当前模版组下该模版编号已存在");
                return msg;
            }
            if (mapper.insert(bean) != 1) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                return msg;
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error("模版保存失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("update")
    @Override
    public MessageBean update(SessionFactory factory, StaffBean user, ProcessUpdateBean bean) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            if (StringUtils.isEmpty(bean.getId())) {
                msg.setCode(BusinessCode.EMPTY_PARAM.getCode());
                msg.setDescription("没有获取到当前业务ID");
                return msg;
            }
            if (StringUtils.isEmpty(bean.getAppId()) || StringUtils.isEmpty(bean.getSetId()) ||
                    StringUtils.isEmpty(bean.getCode()) || StringUtils.isEmpty(bean.getName())) {
                msg.setCode(BusinessCode.EMPTY_PARAM.getCode());
                msg.setDescription(BusinessCode.EMPTY_PARAM.getDescription());
                return msg;
            }
            DisposeBeanUtil.disposeUpdate(user, bean);
            ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
            // 验证 code 是否已经存在
            if (mapper.verifyCode(bean.getCode(), bean.getSetId(), bean.getId()) > 0) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("当前模版组下该模版编号已存在");
                return msg;
            }
            if (mapper.updateProcess(bean) != 1) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                return msg;
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error("模版修改失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("delete")
    @Override
    public MessageBean delete(SessionFactory factory, String id) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
            // 根据ID删除 模版管理
            if (mapper.delete(id) != 1) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                return msg;
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error("模版删除失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("copyProcess")
    @Override
    public MessageBean copyProcess(SessionFactory factory, String copyId, String code, String name) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
            ProcessQueryBean bean = mapper.queryForObject(copyId);
            if (bean == null) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("该模版已被删除");
                return msg;
            }
            // 验证 code 是否已经存在
            if (mapper.verifyCode(code, bean.getSetId(), null) > 0) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("当前模版组下该模版编号已存在");
                return msg;
            }
            // 复制后的模版id
            String id = WorkflowUtil.getObjectId();
            // 根据ID复制 模版管理
            if (mapper.copyProcess(copyId, id, code, name) != 1) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                return msg;
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error("模版复制失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("queryDesignProcessList")
    @Override
    public List<Map> queryDesignProcessList(SessionFactory factory, StaffBean user) {
        ProcessSetMapper processSetMapper = factory.getMapper(ProcessSetMapper.class);
        // 根据用户帐号 查询系统管理员ID
        String administratorId = processSetMapper.queryAdminIdByUsercode(user.getAccount());
        ProcessMapper processMapper = factory.getMapper(ProcessMapper.class);
        // 根据系统管理员ID 查询用户有设计权限的模版组
        List<Map> list = processMapper.queryDesignProcessList(administratorId);
        if (list == null || list.size() < 1) {
            return list;
        }
        List<Map> appProcessList = new LinkedList();
        list.stream().forEach(map -> {
            if (!appProcessList.stream().map(appProcess -> appProcess.get("appId").toString()).collect(Collectors.toList())
                    .contains(map.get("appId").toString())) {
                Map appProcessMap = new HashMap();
                String appId = map.get("appId").toString();
                appProcessMap.put("appId", appId);
                appProcessMap.put("appName", map.get("appName").toString());
                appProcessMap.put("label", map.get("appName").toString());
                appProcessMap.put("appCode", map.get("appCode").toString());
                List setList = new LinkedList();
                list.stream().forEach(map1 -> {
                    if (map1.get("setAppId") != null && appId.equals(map1.get("setAppId").toString())) {
                        map1.put("label", map1.get("setName").toString());
                        setList.add(map1);
                    }
                });
                appProcessMap.put("sets", setList);
                appProcessList.add(appProcessMap);
            }
        });
        return appProcessList;
    }

    @Override
    @TaskAnnotation("getProcess")
    public ProcessBean getProcess(SessionFactory factory, String appCode, String setCode, String processCode) {
        ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
        return mapper.getProcess(appCode, setCode, processCode);
    }

    @Override
    @TaskAnnotation("validateProcessCode")
    public boolean validateProcessCode(SessionFactory factory, String processCode) {
        ProcessMapper mapper = factory.getMapper(ProcessMapper.class);
        ProcessBean processBean = mapper.queryByCode(processCode);
        return processBean != null;
    }

    @TaskAnnotation("list")
    @Override
    public ProcessListQueryBean list(SessionFactory factory, StaffBean user, String secret, String setCode,
                                     String processCode, String billId, String title, String startDate,
                                     String endDate, Integer type, Integer status, String operator,
                                     Integer page, Integer pageSize) {
        ProcessListQueryBean queryBean = new ProcessListQueryBean();
        return queryBean;
    }

    @TaskAnnotation("define")
    @Override
    public List<Map<String, String>> define(SessionFactory factory, String secret, String setCode, String processCode) {
        return activitiService.workflowDefine(setCode + processCode);
    }

}
